﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Client;
using MO_NET = Microsoft.SharePoint.Client;

namespace BAL.PublishSharepoint
{
    public class PublishSP
    {
        #region properties

        string _context;
        public string context
        {
            get { return _context; }
            set { _context = value; }
        }

        string _libName;
        public string libName
        {
            get { return _libName; }
            set { _libName = value; }
        }

        string _fileName;
        public string fileName
        {
            get { return _fileName; }
            set { _fileName = value; }
        }

        string _fullPathFile;
        public string fullPathFile
        {
            get { return _fullPathFile; }
            set { _fullPathFile = value; }
        }

        string _usrCreator;
        public string usrCreator
        {
            get { return _usrCreator; }
            set { _usrCreator = value; }
        }

        //public string territorio{get;set;}
        //public string title{get;set;}

        private string _pathDwnldFromWkpnt;
        public string pathDwnldFromWkpnt
        {
            get { return _pathDwnldFromWkpnt; }
            set { _pathDwnldFromWkpnt = value; }
        }

        string _unidVersion;
        public string unidVersion
        {
            get { return _unidVersion; }
            set { _unidVersion = value; }
        }

        private List<string> filesToDelete;
        #endregion

        public PublishSP(string context, string libName, string fileName, string fullPathFile, string usrCreator)//, string territorio)
        {
            this.context = context;
            this.libName = libName;
            this.fileName = fileName;
            this.fullPathFile = fullPathFile;
            this.usrCreator = usrCreator;
            //this.territorio = territorio;
        }// constructor

        public PublishSP(string context, string libName,string version, string pathDestino)
        {
            this.context = context;
            this.libName = libName;
            //this.fileName = fileName;
            //this.fullPathFile = fullPathFile;
            this.pathDwnldFromWkpnt = pathDestino;
            this.usrCreator = usrCreator;
            //this.territorio = territorio;
            this.unidVersion = version;
        }// constructor

        public PublishSP(string context, string libName, string version, List<string> filesToDel)
        {
            this.context = context;
            this.libName = libName;
            this.usrCreator = usrCreator;
            this.unidVersion = version;
            this.filesToDelete = filesToDel;
        }// constructor

        public void PublishTPOSM(string title, string territorio, string iniciativa, string totalPos, string tiempoImplement)
        {
            using (MO_NET.ClientContext ctx = new MO_NET.ClientContext(context))
            {
                ctx.AuthenticationMode = ClientAuthenticationMode.Default;
                //Publicar en sharepoint 
                MO_NET.List lBibliotecaDocumentos = ctx.Web.Lists.GetByTitle(this.libName);//lista donde se va a publicar   
                MO_NET.FileCreationInformation fciArchivo = new MO_NET.FileCreationInformation();
                fciArchivo.Content = System.IO.File.ReadAllBytes(this.fullPathFile);
                fciArchivo.Url = this.fileName;
                fciArchivo.Overwrite = true;

                // ----- archivo a subir
                MO_NET.File fToUpload = lBibliotecaDocumentos.RootFolder.Files.Add(fciArchivo);
                ctx.Load(fToUpload);    // carga el archivo en el contexto

                // ----- Lista de territorios
                CamlQuery query = new CamlQuery();
                query.ViewXml = "<Where><Eq><FieldRef Name='Territorio'/><Value Type='Text'>" + territorio + "</Value></Eq></Where>";
                MO_NET.List lstTerr = ctx.Web.Lists.GetByTitle("Territorios");
                ListItemCollection lterr = lstTerr.GetItems(query);

                // ------ lista de ContentTypes de la librería
                ContentTypeCollection cntType = lBibliotecaDocumentos.ContentTypes;
                //ctx.Web.AvailableContentTypes;

                //------ obtiene usuario
                FieldUserValue userValue = new FieldUserValue();
                User usr = ctx.Web.EnsureUser(this.usrCreator);


                ctx.Load(lterr);    //carga en el contexto el territorio
                ctx.Load(cntType);  //carga en el contexto la lista de ContentTypes
                ctx.Load(usr);      //carga en el contexto el usuario creador

                ctx.ExecuteQuery();

                // obtiene el id del usuario
                userValue.LookupId = usr.Id;

                //int count = cntType.Count;  //lterr.Count;

                // se selecciona el item al que se le va a pegar la metadata
                ListItem item1 = fToUpload.ListItemAllFields;

                // ------------------------- Actualización de Metadata

                item1["Title"] = title; //"Prueba!"
                foreach (var it in lterr)
                    if (it["Title"].ToString() == territorio)   // == "820603")
                        item1["Territorio"] = it["ID"].ToString();

                //item1["ContentType"] = "{0x0101007541816EC8D84703978A41D15BDA2670030500AE706FE6D55B2248BC14B28B2D12B22E}";
                //item1["FileLeafRef"] = "Pruebaaaaa";//SOLO LECTURA
                item1["Iniciativa"] = iniciativa;   //"Iniciativa 33";
                item1["Autor0"] = userValue;
                item1["Total_x0020_POS0"] = totalPos;    //"5";
                item1["Tiempo_x0020_de_x0020_Implementaci_x00f3_n"] = tiempoImplement;  //"12";

                // se actualiza la metadata
                item1.Update();
                ctx.ExecuteQuery();
            }//using
        }//PublishTPOSM

        public void PublishCEA(string title, string territorio, string totalPos, string tiempoImplement, string usrApprob1, string usrApprob2)
        {
            using (MO_NET.ClientContext ctx = new MO_NET.ClientContext(context))
            {
                ctx.AuthenticationMode = ClientAuthenticationMode.Default;
                //Publicar en sharepoint 
                MO_NET.List lBibliotecaDocumentos = ctx.Web.Lists.GetByTitle(this.libName);//lista donde se va a publicar   
                MO_NET.FileCreationInformation fciArchivo = new MO_NET.FileCreationInformation();
                fciArchivo.Content = System.IO.File.ReadAllBytes(this.fullPathFile);
                fciArchivo.Url = this.fileName;
                fciArchivo.Overwrite = true;

                // ----- archivo a subir
                MO_NET.File fToUpload = lBibliotecaDocumentos.RootFolder.Files.Add(fciArchivo);
                ctx.Load(fToUpload);    // carga el archivo en el contexto

                // ----- Lista de territorios
                CamlQuery query = new CamlQuery();
                query.ViewXml = "<Where><Eq><FieldRef Name='Territorio'/><Value Type='Text'>" + territorio + "</Value></Eq></Where>";
                MO_NET.List lstTerr = ctx.Web.Lists.GetByTitle("Territorios");
                ListItemCollection lterr = lstTerr.GetItems(query);

                // ------ lista de ContentTypes de la librería
                ContentTypeCollection cntType = lBibliotecaDocumentos.ContentTypes;
                //ctx.Web.AvailableContentTypes;

                //------ obtiene usuario
                FieldUserValue userValue = new FieldUserValue();
                User usr = ctx.Web.EnsureUser(this.usrCreator);

                // -----  obtiene a los 2 aprobadores
                FieldUserValue userAppr1 = new FieldUserValue();
                User usrAppr1 = ctx.Web.EnsureUser(usrApprob1);
                FieldUserValue userAppr2 = new FieldUserValue();
                User usrAppr2 = ctx.Web.EnsureUser(usrApprob2);

                ctx.Load(lterr);    //carga en el contexto el territorio
                ctx.Load(cntType);  //carga en el contexto la lista de ContentTypes
                ctx.Load(usr);      //carga en el contexto el usuario creador
                ctx.Load(usrAppr1);
                ctx.Load(usrAppr2);

                ctx.ExecuteQuery();

                // obtiene el id del usuario
                userValue.LookupId = usr.Id;
                // obtiene los IDs de los aprobadores
                userAppr1.LookupId = usrAppr1.Id;
                userAppr2.LookupId = usrAppr2.Id;

                //int count = cntType.Count;  //lterr.Count;

                // se selecciona el item al que se le va a pegar la metadata
                ListItem item1 = fToUpload.ListItemAllFields;

                // ------------------------- Actualización de Metadata

                //item1["ContentType"] = "{0x0101007541816EC8D84703978A41D15BDA2670030500AE706FE6D55B2248BC14B28B2D12B22E}";
                //item1["FileLeafRef"] = "Pruebaaaaa";//SOLO LECTURA

                item1["Title"] = title; //"Prueba!"
                item1["Autor"] = userValue;
                item1["Total_x0020_POS"] = totalPos;    //"5";
                item1["Tiempo_x0020_de_x0020_Implementaci_x00f3_n"] = tiempoImplement;  //"12";
                item1["Aprobador_x0020_1"] = userAppr1;
                item1["Aprobador_x0020_2"] = userAppr2;

                foreach (var it in lterr)
                    if (it["Title"].ToString() == territorio)   // == "820603")
                        item1["Territorio"] = it["ID"].ToString();

                // se actualiza la metadata
                item1.Update();
                ctx.ExecuteQuery();

            }//using
        }//

        public void PublishREA(string title, string territorio, string totalPos, string tiempoImplement, string usrApprob1)
        {
            using (MO_NET.ClientContext ctx = new MO_NET.ClientContext(context))
            {
                ctx.AuthenticationMode = ClientAuthenticationMode.Default;
                //Publicar en sharepoint 
                MO_NET.List lBibliotecaDocumentos = ctx.Web.Lists.GetByTitle(this.libName);//lista donde se va a publicar   
                MO_NET.FileCreationInformation fciArchivo = new MO_NET.FileCreationInformation();
                fciArchivo.Content = System.IO.File.ReadAllBytes(this.fullPathFile);
                fciArchivo.Url = this.fileName;
                fciArchivo.Overwrite = true;

                // ----- archivo a subir
                MO_NET.File fToUpload = lBibliotecaDocumentos.RootFolder.Files.Add(fciArchivo);
                ctx.Load(fToUpload);    // carga el archivo en el contexto

                // ----- Lista de territorios
                CamlQuery query = new CamlQuery();
                query.ViewXml = "<Where><Eq><FieldRef Name='Territorio'/><Value Type='Text'>" + territorio + "</Value></Eq></Where>";
                MO_NET.List lstTerr = ctx.Web.Lists.GetByTitle("Territorios");
                ListItemCollection lterr = lstTerr.GetItems(query);

                // ------ lista de ContentTypes de la librería
                ContentTypeCollection cntType = lBibliotecaDocumentos.ContentTypes;
                //ctx.Web.AvailableContentTypes;

                //------ obtiene usuario
                FieldUserValue userValue = new FieldUserValue();
                User usr = ctx.Web.EnsureUser(this.usrCreator);

                // -----  obtiene a los 2 aprobadores
                FieldUserValue userAppr1 = new FieldUserValue();
                User usrAppr1 = ctx.Web.EnsureUser(usrApprob1);

                ctx.Load(lterr);    //carga en el contexto el territorio
                ctx.Load(cntType);  //carga en el contexto la lista de ContentTypes
                ctx.Load(usr);      //carga en el contexto el usuario creador
                ctx.Load(usrAppr1);

                ctx.ExecuteQuery();

                // obtiene el id del usuario
                userValue.LookupId = usr.Id;
                // obtiene los id del aprobador
                userAppr1.LookupId = usrAppr1.Id;

                //int count = cntType.Count;  //lterr.Count;

                // se selecciona el item al que se le va a pegar la metadata
                ListItem item1 = fToUpload.ListItemAllFields;

                // ------------------------- Actualización de Metadata

                //item1["ContentType"] = "{0x0101007541816EC8D84703978A41D15BDA2670030500AE706FE6D55B2248BC14B28B2D12B22E}";
                //item1["FileLeafRef"] = "Pruebaaaaa";//SOLO LECTURA

                item1["Title"] = title; //"Prueba!"
                item1["Autor0"] = userValue;
                item1["Total_x0020_POS0"] = totalPos;    //"5";
                item1["Tiempo_x0020_de_x0020_Implementaci_x00f3_n0"] = tiempoImplement;  //"12";
                item1["Aprobador_x0020_1"] = userAppr1;

                foreach (var it in lterr)
                    if (it["Title"].ToString() == territorio)   // == "820603")
                        item1["Territorio"] = it["ID"].ToString();

                // se actualiza la metadata
                item1.Update();
                ctx.ExecuteQuery();

            }//using
        }//


        public void DownloadFilesFromSP()   //(string context, string listName, string pathDestino, string version)
        {
            try
            {
                
                using (MO_NET.ClientContext ctx = new MO_NET.ClientContext(context))
                {
                    ctx.AuthenticationMode = ClientAuthenticationMode.Default;
                    //Publicar en sharepoint 
                    MO_NET.List lBibliotecaDocumentos = ctx.Web.Lists.GetByTitle(this.libName);//lista donde se va a publicar 
                    CamlQuery query = new CamlQuery();
                    query.ViewXml = "<Query><Where><Eq><FieldRef Name='Activida'/><Value Type='WorkFlowStatus'>Approved</Value></Eq></Where></Query>";
                    //Approved
                    ListItemCollection lterr = lBibliotecaDocumentos.GetItems(query);

                    ctx.Load(lterr);
                    ctx.ExecuteQuery();


                    List<string> latest = this.getLatestFilesList(lterr);

                    //ListItem item = lterr[12];
                    foreach (ListItem item in lterr)
                    {
                        if (item != null)
                        {

                            string fileRef = item["FileRef"].ToString();
                            string filename = fileRef.Substring(fileRef.LastIndexOf('/') + 1);

                            //if (filename.Split('_')[0] == "5" && item["Activida"].ToString().Split('_')[0] == this.unidVersion)
                            if (latest.Contains(filename.Split('.')[0]))
                            {
                                string f = this.pathDwnldFromWkpnt + filename; //@"C:\Users\ialdasor\Desktop\temp\" + filename;

                                //FileInformation 
                                var fileinfo = MO_NET.File.OpenBinaryDirect(ctx, fileRef);

                                IList<byte> content = new List<byte>();
                                int b;

                                while ((b = fileinfo.Stream.ReadByte()) != -1)
                                {
                                    content.Add((byte)b);
                                }

                                System.IO.File.WriteAllBytes(f, content.ToArray());
                                fileinfo.Stream.Close();
                            }
                        }
                    }// foreach

                }//using
            }
            catch (Exception ex)
            {
                
                throw ex;
            }
        }//

        private List<string> getLatestFilesList(ListItemCollection lterr)
        {
            List<string> arr = new List<string>();

            foreach (ListItem item in lterr)
            {
                string fileRef = item["FileRef"].ToString();
                string filename = fileRef.Substring(fileRef.LastIndexOf('/') + 1);

                if (filename.Split('_')[0] == this.unidVersion && item["Activida"].ToString() == "16")
                    arr.Add(item["FileRef"].ToString());
            }

            return ConsFileInfo.GetLatest(arr);

        }

        public void DeleteFilesFromWorkpoint()
        {
            try
            {
                using (MO_NET.ClientContext ctx = new MO_NET.ClientContext(this.context))
                {
                    ctx.AuthenticationMode = ClientAuthenticationMode.Default;
                    MO_NET.List lBibliotecaDocumentos = ctx.Web.Lists.GetByTitle(this.libName);//lista de donde se van a borrar archivos
                    CamlQuery query = new CamlQuery();
                    query.ViewXml = "<Query><Where><Eq><FieldRef Name='Activida'/><Value Type='WorkFlowStatus'>Approved</Value></Eq></Where></Query>";
                    
                    ListItemCollection lterr = lBibliotecaDocumentos.GetItems(query);

                    ctx.Load(lterr);
                    ctx.ExecuteQuery();

                    foreach (ListItem item in lterr)
                    {
                        if (item != null)
                        {
                            string fileRef = item["FileRef"].ToString();
                            string filename = fileRef.Substring(fileRef.LastIndexOf('/') + 1);

                            if (this.filesToDelete.Contains(filename.Split('.')[0]))
                            {
                                item.DeleteObject();
                                ctx.ExecuteQuery();
                    
                            }
                        }
                    }// foreach

                }//using
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }//

        public void DeleteFileFormLibrary()
        {
            try 
	        {
                using (ClientContext clientContext = new ClientContext(this.context))
                {
                    foreach (string fi in this.filesToDelete)
                    {
                        string attachmentPath = string.Empty;
                        attachmentPath = string.Format("/{0}/{1}", this.libName, System.IO.Path.GetFileName(fi+".xlsx"));
                    
                        var file = clientContext.Web.GetFileByServerRelativeUrl(attachmentPath);
                        file.DeleteObject();
                        clientContext.ExecuteQuery();
                    }//foreach
                   
                }//using    
	        }
	        catch (Exception ex)
	        {
		        throw ex;
	        }
        }//

    }// end class


    public class ConsFileInfo
    {
        private long _unidVersion;
        private string _idRecurso;
        private long _dateLoaded;

        public long UnidVersion
        {
            get { return _unidVersion; }
            set { _unidVersion = value; }
        }
        public string IdRecurso
        {
            get { return _idRecurso; }
            set { _idRecurso = value; }
        }
        public long DateLoaded
        {
            get { return _dateLoaded; }
            set { _dateLoaded = value; }
        }

        public ConsFileInfo(long unidVersion, string idRecurso, long dateLoaded)
        {
            this._dateLoaded = dateLoaded;
            this._idRecurso = idRecurso;
            this._unidVersion = unidVersion;
        }
        public ConsFileInfo()
        {
        }


        public static List<string> GetLatest(List<string> arr)
        {
            List<ConsFileInfo> cfi = new List<ConsFileInfo>();

            foreach (string item in arr)
            {
                string a = item.Split('/').Last().Split('.')[0];
                long ver = 0, date = 0;
                if (long.TryParse(a.Split('_')[0].ToString(), out ver) && long.TryParse(a.Split('_')[2], out date))
                    cfi.Add(new ConsFileInfo(ver, a.Split('_')[1], date));
            }

            var r = (from f in cfi
                     group f by new { f.UnidVersion, f.IdRecurso } into g
                     select new ConsFileInfo()
                     {
                         UnidVersion = g.Key.UnidVersion,
                         IdRecurso = g.Key.IdRecurso,
                         DateLoaded = g.Max(s => s.DateLoaded)
                     }
                    ).ToList<ConsFileInfo>();

            List<string> latest = new List<string>();

            r.ForEach(
                    a => latest.Add(a.UnidVersion.ToString() + "_" + a.IdRecurso + "_" + a.DateLoaded.ToString())
                );

            return latest;
        }//


    }// end class
}
